﻿using System.Text;
using System.Security.Cryptography;
using System;
using System.IO;
using System.Net;

namespace IMDBApi.Contracts
{
    /// <summary>
    /// A static class which provides all the functions for entcrypting, decrypting, dateTime conversion and file io.
    /// </summary>
    class Utils
    {
        #region Security Cryptography

        /// <summary>
        /// UTF8 Encoding.
        /// </summary>
        private static readonly Encoding encoding = Encoding.UTF8;

        /// <summary>
        /// Decryptes a message with sha1-algorythm.
        /// </summary>
        /// <param name="message">a message to be decrypted</param>
        /// <returns>Returns decrypted message.</returns>
        public static string ComputeSha1(string message = "message")
        {
            string sbinary = string.Empty;
            SHA1 hash = SHA1CryptoServiceProvider.Create();
            byte[] plainTextBytes = encoding.GetBytes(message);
            byte[] hashBytes = hash.ComputeHash(plainTextBytes);
            foreach (byte b in hashBytes)
                sbinary += string.Format("{0:x2}", b);
            return sbinary;
        }

        /// <summary>
        /// Decryptes a message with sha256-algorythm.
        /// </summary>
        /// <param name="key">a key</param>
        /// <param name="message">a message</param>
        /// <returns>Returns decrypted message.</returns>
        public static string ComputeSha256(string key = "key", string message = "message")
        {
            var hash = string.Empty;
            var keyByte = encoding.GetBytes(key);
            using (var hmacsha256 = new HMACSHA256(keyByte))
            {
                hmacsha256.ComputeHash(encoding.GetBytes(message));
                hash = ByteToString(hmacsha256.Hash);
            }
            return hash;
        }

        /// <summary>
        /// Converts bytearray to string.
        /// </summary>
        /// <param name="buff">the bytearray</param>
        /// <returns>Returns decrypted message.</returns>
        private static string ByteToString(byte[] buff)
        {
            string sbinary = string.Empty;
            for (int i = 0; i < buff.Length; i++)
                sbinary += buff[i].ToString("X2"); /* hex format */
            return sbinary;
        }

        #endregion

        #region Unix Timestamp Conversion

        /// <summary>
        /// Unix Timestamp Epoch.
        /// </summary>
        private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

        /// <summary>
        /// Creates a unix timestamp from milliseconds.
        /// </summary>
        /// <returns>Returns a unixtimestamp.</returns>
        public static long GetCurrentUnixTimestampMillis()
        {
            return (long)(DateTime.UtcNow - UnixEpoch).TotalMilliseconds;
        }

        /// <summary>
        /// Creates a DateTime object from unix timestamp milliseconds.
        /// </summary>
        /// <param name="millis">A unix timestamp</param>
        /// <returns>Returns DateTime object.</returns>
        public static DateTime DateTimeFromUnixTimestampMillis(long millis)
        {
            return UnixEpoch.AddMilliseconds(millis);
        }

        /// <summary>
        /// Creates a unix timestamp from milliseconds.
        /// </summary>
        /// <returns>Returns a unixtimestamp.</returns>
        public static long GetCurrentUnixTimestampSeconds()
        {
            return (long)(DateTime.UtcNow - UnixEpoch).TotalSeconds;
        }

        /// <summary>
        /// Creates a DateTime object from unix timestamp seconds.
        /// </summary>
        /// <param name="seconds">A unix timestamp</param>
        /// <returns>Returns DateTime object.</returns>
        public static DateTime DateTimeFromUnixTimestampSeconds(long seconds)
        {
            return UnixEpoch.AddSeconds(seconds);
        }

        #endregion

        #region File IO / Web IO

        /// <summary>
        /// Reads a filename or website
        /// </summary>
        /// <param name="url">a IMDB url or file.</param>
        /// <returns>Returns contents of url.</returns>
        public static string file_get_contents(string url)
        {
            string contents = string.Empty;
            if (url.ToLower().IndexOf("http:") > -1)
            {
                WebClient client = new WebClient();
                byte[] response = client.DownloadData(url);
                contents = Encoding.ASCII.GetString(response);
            }
            else
            {
                StreamReader reader = new StreamReader(url);
                contents = reader.ReadToEnd();
                reader.Close();
            }
            return contents;
        }

        #endregion
    }
}
